package com.ruoyi.ams.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Sets;
import com.ruoyi.ams.domain.AmsAssetInfoChange;
import com.ruoyi.ams.domain.AmsAssetInfoChangeDetail;
import com.ruoyi.ams.domain.bo.ChangeAssetInfoBo;
import com.ruoyi.ams.service.AmsReusingService;
import com.ruoyi.ams.service.IAmsAssetInfoChangeDetailService;
import com.ruoyi.ams.service.IAmsAssetInfoChangeService;
import com.ruoyi.asms.service.IAsmsAssetFullInfoService;
import com.ruoyi.common.core.domain.AsmsAssetFullInfo;
import com.ruoyi.common.core.domain.KeyValueVo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.security.annotation.PreAuthorize;
import com.ruoyi.system.controller.SysUserController;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 实物信息变更Controller
 * 
 * @author yfkj
 * @date 2022-05-16
 */
@RestController
@RequestMapping("/ams/change")
public class AmsAssetInfoChangeController extends BaseController
{
    @Autowired
    private IAmsAssetInfoChangeService amsAssetInfoChangeService;

//    @Autowired
//    private IAsmsAssetFullInfoService assetFullInfoService;
   @Autowired
    private IAsmsAssetFullInfoService assetFullInfoService;
    @Autowired
    private AmsReusingService amsReusingService;
    @Autowired
    private IAmsAssetInfoChangeDetailService assetInfoChangeDetailService;
//    @Autowired
//    private RemoteUserService remoteUserService;
    @Autowired
    private SysUserController userController;

    /**
     * 查询实物信息变更列表
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:change:list")
    @ApiOperation(value = "获取实物信息变更列表")
    @GetMapping("/getAmsAssetInfoChangeList")
    public TableDataInfo getAmsAssetInfoChangeList(@RequestParam(value = "status", required = false) String status,
                                                   @RequestParam(value = "code", required = false) String code)
    {
        QueryWrapper<AmsAssetInfoChange> wrapper = new QueryWrapper<>();
        if (status != null) {
            wrapper.eq(AmsAssetInfoChange.STATUS, status);
        }
        if (code != null) {
            AsmsAssetFullInfo assetFullInfo = assetFullInfoService
                    .getOne(new QueryWrapper<AsmsAssetFullInfo>()
                            .eq(AsmsAssetFullInfo.ASSET_CODE, code)
                            .or().eq(AsmsAssetFullInfo.SN, code), false);
            if (assetFullInfo != null) {
                wrapper.eq(AmsAssetInfoChange.ASSET_ID, assetFullInfo.getAssetId());
            }
        }
        wrapper.orderByDesc(AmsAssetInfoChange.ASSET_INFO_CHANGE_ID);
        startPage();
        List<AmsAssetInfoChange> list = amsAssetInfoChangeService.list(wrapper);

        CompletableFuture<R<Map<Long, SysUser>>> future1 = CompletableFuture.supplyAsync(() ->
                userController.getAllUsers());

        CompletableFuture<List<AsmsAssetFullInfo>> future4 = CompletableFuture.supplyAsync(() ->
                assetFullInfoService.list(new QueryWrapper<AsmsAssetFullInfo>()
                        .select(AsmsAssetFullInfo.ASSET_ID, AsmsAssetFullInfo.ASSET_CODE, AsmsAssetFullInfo.ASSET_TYPE_NAME)));

        R<Map<Long, SysUser>> allUsers = new R<>();
        HashMap<Long, AsmsAssetFullInfo> assetInfoMap = new HashMap<>();
        List<AsmsAssetFullInfo> fullInfos = new ArrayList<>();
        try {
            allUsers = future1.get();
            if (allUsers.getCode() == R.FAIL) {
                return amsReusingService.resovleError();
            }
            fullInfos = future4.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        for (AsmsAssetFullInfo fullInfo : fullInfos) {
            assetInfoMap.put(fullInfo.getAssetId(), fullInfo);
        }
        Map<Long, SysUser> userMap = allUsers.getData();
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy.MM.dd");

        for (AmsAssetInfoChange change : list) {
            if (change.getAssetId() != null) {
                AsmsAssetFullInfo assetFullInfo = assetInfoMap.get(change.getAssetId());
                if (assetFullInfo != null) {
                    change.setAssetCode(assetFullInfo.getAssetCode());
                    change.setAssetTypeName(assetFullInfo.getAssetTypeName());
                }
            }
            if (change.getChangeTime() != null) {
                change.setChangeTimeStr(fmt.format(new Date(change.getChangeTime())));
            }
            if (change.getChargerId() != null) {
                SysUser sysUser = userMap.get(change.getChargerId());
                if (sysUser != null) {
                    change.setChargerName(sysUser.getNickName());
                }
            }
        }

        return getDataTable(list, 10);
    }

    /**
     * 获取实物信息变更详细信息
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:change:query")
    //@ApiOperation(value = "获取实物信息变更详情")
    @GetMapping(value = "/getAmsAssetInfoChangeById")
    public AjaxResult getAmsAssetInfoChangeById(@RequestParam("assetInfoChangeId") Long assetInfoChangeId)
    {
        return AjaxResult.success(amsAssetInfoChangeService.selectAmsAssetInfoChangeByAssetInfoChangeId(assetInfoChangeId));
    }

    /**
     * 新增实物信息变更
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:change:add")
    @Log(title = "实物信息变更", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增实物信息变更")
    @PostMapping(value = "/addAmsAssetInfoChange")
    public AjaxResult addAmsAssetInfoChange(@RequestBody AmsAssetInfoChange amsAssetInfoChange)
    {
        amsAssetInfoChange.setSn(amsReusingService.createSn());
        amsAssetInfoChange.setChangeTime(System.currentTimeMillis());
        return toAjax(amsAssetInfoChangeService.save(amsAssetInfoChange));
    }

    /**
     * 修改实物信息变更
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:change:edit")
    @Log(title = "实物信息变更", businessType = BusinessType.UPDATE)
    //@ApiOperation(value = "修改实物信息变更")
    @PostMapping(value = "/editAmsAssetInfoChange")
    public AjaxResult editAmsAssetInfoChange(@RequestBody AmsAssetInfoChange amsAssetInfoChange)
    {
        return toAjax(amsAssetInfoChangeService.updateById(amsAssetInfoChange));
    }

    /**
     * 删除实物信息变更
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:change:remove")
    @Log(title = "实物信息变更", businessType = BusinessType.DELETE)
	@GetMapping("/removeAmsAssetInfoChanges")
    public AjaxResult removeAmsAssetInfoChanges(@RequestParam Long[] assetInfoChangeIds)
    {
        return toAjax(amsAssetInfoChangeService.deleteAmsAssetInfoChangeByAssetInfoChangeIds(assetInfoChangeIds));
    }
    @GetMapping("/getAmsAssetInfoChangeNamesForSelect")
    //@ApiOperation(value = "获取实物信息变更名称列表用于下拉搜索")
    public AjaxResult getAmsAssetInfoChangeNamesForSelect()
    {
        List<AmsAssetInfoChange> list = amsAssetInfoChangeService.list();//自行加条件
        List<KeyValueVo> resultList = new ArrayList<>();
        for (AmsAssetInfoChange amsAssetInfoChange: list ) {
            KeyValueVo vo = new KeyValueVo();
            //vo.setKey(it.getId());
            //vo.setValue(it.getName());
            resultList.add(vo);
        }
        return AjaxResult.success(resultList);
    }

    /**
     * 导出实物信息变更列表
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:change:export")
    @Log(title = "实物信息变更", businessType = BusinessType.EXPORT)
    @PostMapping("/exportAmsAssetInfoChange")
    public String exportAmsAssetInfoChange(HttpServletResponse response, AmsAssetInfoChange amsAssetInfoChange) throws IOException
    {
        List<AmsAssetInfoChange> list = amsAssetInfoChangeService.selectAmsAssetInfoChangeList(amsAssetInfoChange);
        ExcelUtil<AmsAssetInfoChange> util = new ExcelUtil<AmsAssetInfoChange>(AmsAssetInfoChange.class);
        util.exportExcel(response, list, "实物信息变更数据");
        return "";
    }

    @ApiOperation("批量变更资产信息（审核通过后修改资产数据）")
    @PostMapping("/changeAssetInfo")
    public AjaxResult changeAssetInfo(@RequestBody ChangeAssetInfoBo bo) {
        if (bo.getAssetIds().length == 0) {
            return AjaxResult.error("请选择至少一条资产数据");
        }
        //存储资产的变更记录
        List<AmsAssetInfoChange> changes = new ArrayList<>();
        String sn = amsReusingService.createSn();
        for (Long assetId : bo.getAssetIds()) {
            AmsAssetInfoChange amsAssetInfoChange = new AmsAssetInfoChange();
            amsAssetInfoChange.setSn(sn);
            amsAssetInfoChange.setAssetId(assetId);
            amsAssetInfoChange.setChangeTime(System.currentTimeMillis());
            amsAssetInfoChange.setChargerId(SecurityUtils.getUserId());
            amsAssetInfoChange.setStatus("2");
            changes.add(amsAssetInfoChange);
        }
        amsAssetInfoChangeService.saveBatch(changes);

        List<AsmsAssetFullInfo> assets = assetFullInfoService.list(new QueryWrapper<AsmsAssetFullInfo>()
                .in(AsmsAssetFullInfo.ASSET_ID, Sets.newHashSet(bo.getAssetIds())));
        HashMap<Long, AsmsAssetFullInfo> assetMap = new HashMap<>();
        assets.forEach(item -> assetMap.put(item.getAssetId(), item));

        //存储资产的变更记录详情
        List<AmsAssetInfoChangeDetail> list = new ArrayList<>();
        List<AmsAssetInfoChangeDetail> details = bo.getDetails();
        for (AmsAssetInfoChange change : changes) {
            AsmsAssetFullInfo asset = assetMap.get(change.getAssetId());
            if (details.size() > 0) {
                for (AmsAssetInfoChangeDetail detail : details) {
                    AmsAssetInfoChangeDetail changeDetail = new AmsAssetInfoChangeDetail();
                    BeanUtils.copyProperties(detail, changeDetail);
                    changeDetail.setAssetInfoChangeId(change.getAssetInfoChangeId());
                    try {
                        Field field = asset.getClass().getDeclaredField(detail.getAttributeEn());
                        field.setAccessible(true);
                        changeDetail.setOldValue(String.valueOf(field.get(asset)));
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    list.add(changeDetail);
                }
            }
        }
        assetInfoChangeDetailService.saveBatch(list);
        checkUpdateAssetInfo(bo.getAssetIds());
        return AjaxResult.success();
    }

    @ApiOperation("审核通过变更资产数据")
    @PostMapping("/checkUpdateAssetInfo")
    public AjaxResult checkUpdateAssetInfo(Long[] assetIds) {
        if (assetIds.length == 0) {
            return AjaxResult.error("请选择至少一条资产");
        }

        //查询符合条件的资产变更记录
        List<AmsAssetInfoChange> changes = amsAssetInfoChangeService.list(new QueryWrapper<AmsAssetInfoChange>()
                .in(AmsAssetInfoChange.ASSET_ID, Sets.newHashSet(assetIds)));

        //查询符合条件的资产变更详情记录
        HashSet<Long> changeIds = new HashSet<>();
        changes.forEach(item -> changeIds.add(item.getAssetInfoChangeId()));
        List<AmsAssetInfoChangeDetail> detailList = assetInfoChangeDetailService
                .list(new QueryWrapper<AmsAssetInfoChangeDetail>()
                .in(AmsAssetInfoChangeDetail.ASSET_INFO_CHANGE_ID, changeIds)
                .eq(AmsAssetInfoChangeDetail.EDIT_OR_SHOW, 0)
                .or().eq(AmsAssetInfoChangeDetail.EDIT_OR_SHOW, 2));

        //构造资产与资产变更详情的一对多的map
        HashMap<Long, List<AmsAssetInfoChangeDetail>> assetIdChangeDetailsMap = new HashMap<>();
        for (AmsAssetInfoChange change : changes) {
            List<AmsAssetInfoChangeDetail> changeDetails = new ArrayList<>();
            for (AmsAssetInfoChangeDetail detail : detailList) {
                if (detail.getAssetInfoChangeId().equals(change.getAssetInfoChangeId())) {
                    changeDetails.add(detail);
                }
            }
            assetIdChangeDetailsMap.put(change.getAssetId(), changeDetails);
        }

        //获取资产详细数据
        List<AsmsAssetFullInfo> assets = assetFullInfoService.list(new QueryWrapper<AsmsAssetFullInfo>()
                .in(AsmsAssetFullInfo.ASSET_ID, Sets.newHashSet(assetIds)));
        HashMap<Long, AsmsAssetFullInfo> assetMap = new HashMap<>();
        assets.forEach(item -> assetMap.put(item.getAssetId(), item));

        //开始修改资产
        List<AsmsAssetFullInfo> infos = new ArrayList<>();
        for (Long assetId : assetIds) {
            AsmsAssetFullInfo asset = assetMap.get(assetId);
            List<AmsAssetInfoChangeDetail> details = assetIdChangeDetailsMap.get(assetId);
            if (asset != null && details != null) {
                for (AmsAssetInfoChangeDetail detail : details) {
                    try {
                        Field field = asset.getClass().getDeclaredField(detail.getAttributeEn());
                        field.setAccessible(true);
                        if (field.getType().equals(Long.class)) {
                            field.set(asset, Long.valueOf(detail.getNewValue()));
                        } else {
                            field.set(asset, detail.getNewValue());
                        }
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
            infos.add(asset);
        }
        assetFullInfoService.updateBatchById(infos);
        return AjaxResult.success();
    }

}
